3.2. Parameter Annotations (@*Param) 参数注解

资源方法中,带有基于参数注解的参数可以从请求中获取信息。前面的一个例子就是在匹配了 @Path 之后,通过 @PathParam 来获取 URL 请求中的路径参数。

@QueryParam 用于从请求 URL 的查询组件中提取查询参数。下面的例子:

Example 3.8. 查询参数

  1. @Path("smooth")
  2. @GET
  3. public Response smooth(
  4. @DefaultValue("2") @QueryParam("step") int step,
  5. @DefaultValue("true") @QueryParam("min-m") boolean hasMin,
  6. @DefaultValue("true") @QueryParam("max-m") boolean hasMax,
  7. @DefaultValue("true") @QueryParam("last-m") boolean hasLast,
  8. @DefaultValue("blue") @QueryParam("min-color") ColorParam minColor,
  9. @DefaultValue("green") @QueryParam("max-color") ColorParam maxColor,
  10. @DefaultValue("red") @QueryParam("last-color") ColorParam lastColor) {
  11. ...
  12. }

如果 step 的参数存在的话,那么附值给它,否则默认是 @DefaultValue定义的值 2。如果 step 的内容不是 32 位的整型,那么会返回404错误。

用户定义了一个 Java 类型 ColorParam,实现如下:

Example 3.9. 自定义 Java 类型用作消耗请求的参数

  1. public class ColorParam extends Color {
  2. public ColorParam(String s) {
  3. super(getRGB(s));
  4. }
  5. private static int getRGB(String s) {
  6. if (s.charAt(0) == '#') {
  7. try {
  8. Color c = Color.decode("0x" + s.substring(1));
  9. return c.getRGB();
  10. } catch (NumberFormatException e) {
  11. throw new WebApplicationException(400);
  12. }
  13. } else {
  14. try {
  15. Field f = Color.class.getField(s);
  16. return ((Color)f.get(null)).getRGB();
  17. } catch (Exception e) {
  18. throw new WebApplicationException(400);
  19. }
  20. }
  21. }
  22. }

一般的,Java 方法的参数类型的可能是:

  • 一个原始类型;
  • 一个接收一个字符串参数的构造函数;
  • 有一个静态方法或一个命名为 fromstring 的方法,用于接收字符串参数,例如Integer.valueOf(String)java.util.UUID.fromString(String)
  • 有一个javax.ws.rs.ext.ParamConverterProvider的 JAX-RS 扩展 SPI 的注册实现, 将返回javax.ws.rs.ext.ParamConverter能转化“字符串”类型的实例;
  • 在 T 满足上面 2 或者 3 个条件时,将会是 List、Set 或者 SortedSet。这样的集合是只读的。

有时参数可以包含相同名称的多个值。如果是这样的话,上面第5条可以用来获得所有的值。

如果 @DefaultValue不与 @QueryParam联合使用,查询参数在请求中如果不存在,List、Set 或者 SortedSet 类型将会是空值集合,对象类型将为空,Java 的定义默认为原始类型。

@PathParam 和其他参数注解 @MatrixParam@HeaderParam@CookieParam@FormParam 遵循与 @QueryParam一样的规则。@MatrixParam 从 URL 路径提取信息。@HeaderParam 从 HTTP 头部提取信息。@CookieParam从关联在 HTTP 头部的 cookies 里提取信息。

@FormParam 稍有特殊,因为它提取信息,先是请求所表示的MIME媒体类型为 application/x-www-form-urlencoded,并且符合指定的 HTML 编码的形式,正如这里所描述的。此参数提取对于 HTML 表单请求是非常有用的,例如从发布的表单数据中提取名称是 name 的参数信息:

Example 3.10. HTML表格处理

  1. @POST
  2. @Consumes("application/x-www-form-urlencoded")
  3. public void post(@FormParam("name") String name) {
  4. // Store the message
  5. }

如果需要通过查询路径参数,从 Map 参数名称获取值,做法以下:

Example 3.11. 从查询参数或者路径获取 Map

  1. @GET
  2. public String get(@Context UriInfo ui) {
  3. MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
  4. MultivaluedMap<String, String> pathParams = ui.getPathParameters();
  5. }

header 和 cookie 参数用法如下:

Example 3.12. 从头部参数获取 Map

  1. @GET
  2. public String get(@Context HttpHeaders hh) {
  3. MultivaluedMap<String, String> headerParams = hh.getRequestHeaders();
  4. Map<String, Cookie> pathParams = hh.getCookies();
  5. }

@Context 一般可以用于获得一个Java类型关联请求或响应的上下文。

因为 form 表单参数(不像其他消息的一部分)是实体,做法如下:

Example 3.13. form 表单参数 获取 Map

  1. @POST
  2. @Consumes("application/x-www-form-urlencoded")
  3. public void post(MultivaluedMap<String, String> formParams) {
  4. // Store the message
  5. }

就是说,不需要@Context注解。

另一种注入是 @BeanParam 允许注入上述参数到一个 bean 。一个 bean 注明@BeanParam含任何属性和适当的参数注解(像
@PathParam)将由预期的相应请求值初始化(如果这些领域在资源类)。然后,跟将请求值(像路径参数)注入到一个构造函数参数或类属性不同的是,@BeanParam可以用于注入这种 bean 到资源或资源的方法。@BeanParam就是用这样的方式聚集更多的请求参数为一个单一的 bean 的情况。

Example 3.14. @BeanParam 用法

  1. public class MyBeanParam {
  2. @PathParam("p")
  3. private String pathParam;
  4. @MatrixParam("m")
  5. @Encoded
  6. @DefaultValue("default")
  7. private String matrixParam;
  8. @HeaderParam("header")
  9. private String headerParam;
  10. private String queryParam;
  11. public MyBeanParam(@QueryParam("q") String queryParam) {
  12. this.queryParam = queryParam;
  13. }
  14. public String getPathParam() {
  15. return pathParam;
  16. }
  17. ...
  18. }

Example 3.15. 将 MyBeanParam 以参数形式注入:

  1. @POST
  2. public void post(@BeanParam MyBeanParam beanParam, String entity) {
  3. final String pathParam = beanParam.getPathParam(); // contains injected path parameter "p"
  4. ...
  5. }

实例展示了@PathParam@QueryParam@MatrixParam@HeaderParam集中在一个 bean 里面。里面的 bean 注射规则如上这些注射相同。@DefaultValue是用来定义矩阵参数的默认值。同时@Encoded注释都有同样的行为,如果它是用来在资源的方法直接注入。将 bean 参数注入到 注解为 @Singleton 的资源类字段是不允许的(注射方法的参数必须替换)。

@BeanParam 可以包含所有的注入参数(@PathParam@QueryParam@MatrixParam@HeaderParam
@CookieParam@FormParam )。

多个 bean 可以被注入到一个资源或方法的参数,即使他们注入相同的请求值。例如,以下是可能的:

Example 3.16. 多个 bean 注入到一个资源或方法

  1. @POST
  2. public void post(@BeanParam MyBeanParam beanParam, @BeanParam AnotherBean anotherBean, @PathParam("p") pathParam,
  3. String entity) {
  4. // beanParam.getPathParam() == pathParam
  5. ...
  6. }